package xyz.comfyz.web.commons.security.access.basic;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import xyz.comfyz.web.commons.security.cache.CacheStorager;
import xyz.comfyz.web.commons.security.model.Token;
import xyz.comfyz.web.commons.security.model.TokenConfig;
import xyz.comfyz.web.commons.security.provider.token.TokenReader;
import xyz.comfyz.web.commons.security.support.AntPathRequestMatcher;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author :    comfy
 * @date :      2018-05-12 16:04:49
 * @since :     1.8
 * <p>
 * http security 配置信息
 */
@Component
public final class HttpSecurity {

    private final TokenConfig tokenConfig = new TokenConfig();
    private final AtomicReference<String> filterPathPattern = new AtomicReference<>(null);
    private final Set<AntPathRequestMatcher> authorizations = new HashSet<>();
    private final Set<AntPathRequestMatcher> exclusions = new HashSet<>();
    private final TreeSet<TokenReader> readers = new TreeSet<>();
    private final Set<CacheStorager<Token>> tokenCaches = new HashSet<>();
    private boolean enableCookie = false;
    private boolean enableLocalCookie = false;

    TokenConfig tokenConfig() {
        return this.tokenConfig;
    }

    boolean enableCookie() {
        return this.enableCookie;
    }

    boolean enableLocalCookie() {
        return this.enableLocalCookie;
    }

    String filterPath() {
        return this.filterPathPattern.get();
    }

    Set<AntPathRequestMatcher> exclusions() {
        return this.exclusions;
    }

    Set<AntPathRequestMatcher> authorizations() {
        return this.authorizations;
    }

    TreeSet<TokenReader> tokenReader() {
        return this.readers;
    }

    Set<CacheStorager<Token>> tokenCache() {
        return this.tokenCaches;
    }

    /*********************** token 配置 *****************************/
    public HttpSecurity tokenConfig(String name, Integer expiry) {
        this.tokenConfig.setName(name).setExpiry(expiry);
        return this;
    }

    public HttpSecurity enableCookie(String domain, String path, boolean enableLocalCookie) {
        this.enableCookie = true;
        this.enableLocalCookie = enableLocalCookie;
        this.tokenConfig.setDomain(domain).setPath(path);

        return this;
    }

    /*********************** filter 配置 *****************************/
    public HttpSecurity filter(String pathPattern) {
        if (StringUtils.hasText(pathPattern))
            this.filterPathPattern.set(pathPattern);
        return this;
    }

    /*********************** metaSources 路径权限 配置 *****************************/
    public HttpSecurity open(String... pathPattern) {
        Arrays.stream(pathPattern).filter(StringUtils::hasText).distinct().map(AntPathRequestMatcher::new).forEach(this.exclusions::add);
        return this;
    }

    public HttpSecurity authorized(String... pathPattern) {
        Arrays.stream(pathPattern).filter(StringUtils::hasText).distinct().map(AntPathRequestMatcher::new).forEach(this.authorizations::add);
        return this;
    }

    /*********************** token获取方式 配置 *****************************/
    public HttpSecurity reader(TokenReader... reader) {
        this.readers.addAll(Arrays.asList(reader));
        return this;
    }

    /*********************** token缓存 配置 *****************************/
    @SafeVarargs
    public final HttpSecurity tokenCache(CacheStorager<Token>... tokenCache) {
        this.tokenCaches.addAll(Arrays.asList(tokenCache));
        return this;
    }

}
